define([
    'goo/entities/GooRunner',
    'goo/statemachine/FSMSystem',
    'goo/addons/howler/systems/HowlerSystem',
    'goo/loaders/DynamicLoader',
    'goo/util/rsvp',
    'js/application/Game',
    'js/io/Input',
    'js/application/Time',
    'js/load/BundleLoader',
    'js/physics/PhysicalWorld',
    'js/game/GameLevel',
    'js/game/PlayerPiece'

], function (
    GooRunner,
    FSMSystem,
    HowlerSystem,
    DynamicLoader,
    RSVP,
    Game,
    Input,
    Time,
    BundleLoader,
    PhysicalWorld,
    GameLevel,
    PlayerPiece
    ) {
    'use strict';


    var goo;

    function initGoo() {
        // Create typical goo application

        goo = new GooRunner({
            antialias: true,
            manuallyStartGameLoop: true,
            debugKeys: true
        });

        BundleLoader.setRootPath('res');
        BundleLoader.setGoo(goo);

        goo.world.setSystem(new Time(goo));
        goo.world.setSystem(new FSMSystem(goo));
        goo.world.setSystem(new HowlerSystem());
        Input.init(goo);
        Game.init(goo);
        GameLevel.setWorld(goo.world);
    }

    function loadGameData(gameData, loadedCallback) {
        GameLevel.setLevelData(gameData.LEVEL_DATA);
        for (var keys in gameData) {
            for (var i = 0; i < gameData[keys].bundles.length; i++) {
                BundleLoader.addBundleToQueue(gameData[keys].bundles[i]);
            }
        }

        var successCallback = function(configsArray)  {
            // If there is a default camera from the scene we remove it here
            var importedCamera = BundleLoader.getLoadedObjectByRef("entities/DefaultToolCamera.entity");
            if (importedCamera) {
                importedCamera.removeFromWorld();
            }
            // Take a peek at the data
            console.log('Loaded Objects:', configsArray);
            loadedCallback();

        };

        var failCallback = function(e) {
            // We just pop up an error message in case the scene fails to load.
            console.log(e.trace);
            alert('Failed to load scene: ' + e);
        };

        BundleLoader.loadBundleQueue(successCallback, failCallback);
    }

    function addLevelPhysicsMesh(levelMesh) {
        var meshData = levelMesh.getComponent("meshDataComponent").meshData;
        PhysicalWorld.addPhysicalWorldMesh(meshData);
    }

    function spawnMob(ref) {
        GameLevel.spawnMobile(ref)
    }

    function configureMobilePieces(mobilePieceData) {
        for (var i = 0; i < mobilePieceData.entities.length; i++) {
            var mob = BundleLoader.getLoadedObjectByRef(mobilePieceData.entities[i].ref);
            mob.transformComponent.transform.scale.set(mobilePieceData.entities[i].scale);
            mob.removeFromWorld();
            GameLevel.registerMobile(mobilePieceData.entities[i].ref, mob, mobilePieceData.entities[i])
        }
    }

    function addPhysicalMeshByRef(ref) {
        var levelMesh = BundleLoader.getLoadedObjectByRef(ref);
        addLevelPhysicsMesh(levelMesh);
    }

    function buildPhysicalWorld(levelData) {
        PhysicalWorld.initPhysics();
        for (var i = 0; i < levelData.physicalMeshes.length; i++) {
            addPhysicalMeshByRef(levelData.physicalMeshes[i])
        }
    }

    function registerKeys() {
        Game.register("Key32", Game, onKey32);
    }

    function onKey32(b0){
        if(b0){
            spawnMob('zombiewalk/entities/RootNode.entity');
        }
    }

    function setupComplete() {
        registerKeys();
        GameLevel.startAutoSpawn();
        PlayerPiece.addPlayerPiece(goo.world);
        goo.renderer.domElement.id = 'goo';
        document.body.appendChild(goo.renderer.domElement);
        goo.startGameLoop();
    }

    return {
        initGoo:initGoo,
        loadGameData:loadGameData,
        buildPhysicalWorld:buildPhysicalWorld,
        configureMobilePieces:configureMobilePieces,
        setupComplete:setupComplete
    };
});
